#pragma once
#include <iostream>
#include <unordered_map>
#include <assert.h>
#include <vector>
#include <fstream>
#include <mysql/mysql.h>
#include "../comm/util.hpp"
#include "../comm/log.hpp"

struct Question
{
    std::string _num;       // 题目编号
    std::string _title;     // 题目标题
    std::string _star;      // 题目难度
    std::string _desc;      // 题目描述
    std::string _header;    // 题目预设给用户在线编辑的代码
    std::string _tail;      // 测试用例，拼接header，形成完整代码
    int _cpu_limit;         // cpu限制
    int _mem_limit;         // 内存限制
};

const std::string oj_questions  = "oj_question";
const std::string host = "127.0.0.1";
const std::string user = "tmp";
const std::string pawd = "";
const std::string db = "oj";
const int port = 3306;

class Model
{
private:
    // 保存题目编号的题目结构的对应关系
    std::unordered_map<std::string, struct Question> _ques;
public:
    Model()
    {
        
    }
    ~Model(){}

    bool QueryMysql(const std::string& sql, std::vector<Question>* out)
    {
        MYSQL* my = mysql_init(nullptr);
        if (mysql_real_connect(my, host.c_str(), user.c_str(), pawd.c_str(), db.c_str(), port, nullptr, 0) == nullptr)
        {
            LOG(FATAL) << "数据库连接失败\n";
            return false;
        }

        // 设置编码格式，不然乱码
        mysql_set_character_set(my, "utf8");
        LOG(INFO) << "连接数据库成功\n";
        // 执行sql语句
        if (mysql_query(my, sql.c_str()) != 0)
        {
            LOG(WARNING) << sql << " execute error!" << "\n";
            return false;
        }

        // 提取结果
        MYSQL_RES* res = mysql_store_result(my);
        // 分析结果
        int rows = mysql_num_rows(res); // 获取行数
        int cols = mysql_num_fields(res); // 获取列数

        Question q;
        for (int i = 0; i < rows; i++)
        {
            MYSQL_ROW row = mysql_fetch_row(res);
            q._num = row[0];
            q._title = row[1];
            q._star = row[2];
            q._desc = row[3];
            q._header = row[4];
            q._tail = row[5];
            q._cpu_limit = atoi(row[6]);
            q._mem_limit = atoi(row[7]);

            out->push_back(q);
        }

        // 释放空间
        mysql_free_result(res);
        // 关闭句柄
        mysql_close(my);
        return true;
    }

    bool GetAllQuestions(std::vector<Question>* out)
    {
        std::string sql = "select * from ";
        sql += oj_questions;
        return QueryMysql(sql, out);
    }

    bool GetOneQuestion(const std::string num, struct Question* q)
    {
        bool res= false;
        std::string sql = "select * from ";
        sql += oj_questions;
        sql += " where num=";
        sql += num;
        std::vector<Question> result;
        if (QueryMysql(sql, &result))
        {
            if (result.size() == 1)
            {
                *q = result[0];
                res = true;
            }
        }

        return res;
    }
};